/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.core.session;

import com.inspur.edp.bef.core.session.distributed.close.SessionRelationBizCacheManger;

import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.lock.service.api.api.DistributedLock;
import io.iec.edp.caf.lock.service.api.api.DistributedLockFactory;
import lombok.SneakyThrows;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@DisallowConcurrentExecution
public class SessionCacheCheckInSys implements Job {

  private static Logger logger = LoggerFactory.getLogger(SessionCacheCheckInSys.class);
  private static final int ExpirationTime = 10;
  private static final String lockId = "bef:runtime_sessionCacheCheck_lock";
  private static final Duration lockTimeOut = Duration.ofMinutes(9);
  private static final Duration waiteLockTime = Duration.ZERO;

  static void startCleanerScheduler() {
    boolean sys = FuncSessionUtil.msuEnabled("Sys");
    boolean redis = FuncSessionUtil.redisEnabled();
    if (sys && redis) {
      FuncSessionUtil
          .startScheduler(SessionCacheCheckInSys.class, "SessionCacheCheckInSys", ExpirationTime, 1);
    } else {
      logger.warn("SessionCacheCheckInSys定时任务未启动:sys-" + sys + ";redis-" + redis);
    }
  }

  @SneakyThrows
  @Override
  public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
   DistributedLock innerLock = null;
    try {
      innerLock = SpringBeanUtils.getBean(DistributedLockFactory.class).tryCreateLock(waiteLockTime,lockId,lockTimeOut);
      if (!innerLock.isAcquired()){
        logger.info("SessionCacheCheckInSys-其他负载正在执行定时任务");
        return;
      }
      logger.info("SessionCacheCheckInSys-执行过期清理定时任务");
      cleanTokenInRedis();
    } catch (Throwable r) {
      logger.error("sys定时任务执行失败一次", r);
    }finally {
      if (innerLock!=null && innerLock.isAcquired()){
        innerLock.close();
      }
    }
  }

  private static synchronized void cleanTokenInRedis() {
    Set<String> tokenIds = SessionRelationBizCacheManger.getInstance().getHashKeySet();
    if (tokenIds == null || tokenIds.isEmpty()) {
      return;
    }

    List<String> removeIds = FuncSessionUtil.isTokenExpired(tokenIds);
//    for (int i =0;i<setNum;i++){
//      List<String> childRemoveIds= getRemoveIds(tokenList,i*10);
//      if (childRemoveIds!=null && childRemoveIds.size()>0){
//        removeIds.addAll(childRemoveIds);
//      }
//    }

    if (removeIds == null || removeIds.isEmpty()){
      return;
    }

    int failedCount = 0;
    Throwable lastError = null;
    for (String removeId : removeIds) {
        try {
          SessionRelationBizCacheManger.getInstance().evict(removeId);
        } catch (Throwable t) {
          failedCount++;
          lastError = t;
        }
    }
    if (failedCount > 0) {
      logger.error("sys定时任务内部失败次数" + failedCount, lastError);
    }
  }

}
